import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringBufferInputStream;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("deprecation")
public class Judge {

	public static void run() throws Exception {
		String clazz = new Exception().getStackTrace()[1].getClassName();
		String datafile = clazz.replace(".", "/").replaceAll("_[^_]*", "") + ".txt";
		doRun(clazz, datafile);
	}

	public static void run(String datafile) throws Exception {
		String clazz = new Exception().getStackTrace()[1].getClassName();
		datafile = clazz.replace(".", "/").replaceAll("[^/]+$", datafile);
		doRun(clazz, datafile);
	}

	static void doRun(String clazz, String datafile) throws Exception {
		// load & hack input
		List<String> demoOut = loadAndHackInput(datafile);

		// hack output & run
		long cost = -System.nanoTime();
		List<String> realOut = runMain(clazz);
		cost += System.nanoTime();

		// compare
		boolean equals = equals(demoOut, realOut);
		System.out.println("------------------------------");
		System.out.println("cost: " + (cost / 1000 / 1000) + " ms");
		System.out.println(equals ? "succ" : "fail");
		if (!equals) {
			System.out.println("--------------- should ---------------");
			for (int i = 0; i < demoOut.size(); i++)
				System.out.println("L" + (i + 1) + ": " + demoOut.get(i));
			System.out.println("--------------- actully ---------------");
			for (int i = 0; i < realOut.size(); i++)
				System.out.println("L" + (i + 1) + ": " + realOut.get(i));
		}
	}

	static List<String> loadAndHackInput(String datafile) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream(datafile)));
		List<String> content = read(in);
		int sep = content.indexOf("------------------------------");

		hackInput(content.subList(0, sep));
		return content.subList(sep + 1, content.size());
	}

	static void hackInput(List<String> input) {
		StringBuilder sb = new StringBuilder();
		for (String line : input)
			sb.append(line).append('\n');
		System.setIn(new StringBufferInputStream(sb.toString()));
	}

	static List<String> runMain(String clazz) throws Exception {
		Class<?> cls = Class.forName(clazz + "$Main");
		Method method = cls.getMethod("main", String[].class);

		PrintStream oriOut = System.out;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		System.setOut(new PrintStream(out));

		try {
			method.invoke(null, (Object) new String[] {});
		} catch (Exception e) {
			e.printStackTrace(oriOut);
		} finally {
			System.setOut(oriOut);
		}

		return read(new BufferedReader(new StringReader(out.toString())));
	}

	static List<String> read(BufferedReader reader) throws IOException {
		List<String> content = new ArrayList<String>();
		String line;
		while ((line = reader.readLine()) != null)
			content.add(line);
		reader.close();
		return content;
	}

	static boolean equals(List<String> demoOut, List<String> realOut) {
		if (demoOut.size() != realOut.size())
			return false;
		boolean ret = true;
		for (int i = 0; i < demoOut.size(); i++) {
			if (!demoOut.get(i).equals(realOut.get(i))) {
				System.out.println("L" + (i + 1) + ":\t>> " + demoOut.get(i));
				System.out.println("\t>> " + realOut.get(i));
				ret = false;
			}
		}
		return ret;
	}

	public static void main(String[] args) throws Exception {
		// doRun("p1000.p1000");
	}

}
